package slick.crud

import slick.jdbc.JdbcProfile
import slick.lifted.TableQuery

import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future, Promise}

/**
 * Slick CRUD util
 *
 * @author Rubin
 * @version v1 2020/8/26 11:52
 */
trait CRUD[M <: Model, R] {

  val database: JdbcProfile#Backend#Database
  val table: AnyRef

  private def getTable: TableQuery[Table[R]] = table.asInstanceOf[TableQuery[Table[R]]]

  def insert(entity: R): Future[Unit] = database.run(DBIO.seq(getTable += entity))

  def delete(fdId: String): Future[Int] = database.run(getTable.filter(_.asInstanceOf[M].fdId === fdId).delete)

  def update(entity: R): Future[Int] = database.run(getTable.insertOrUpdate(entity))

  def findById(fdId: String): Future[R] = database.run(getTable.filter(_.asInstanceOf[M].fdId === fdId).result.head)

  def page(page: Page[R]): Future[Page[R]] = {
    val p = Promise[Page[R]]
    try {
      val data = database.run(getTable.drop(page.page).take(page.limit).result)
      val size = database.run(getTable.size.result)
      page.data = Await.result(data, Duration.Inf)
      page.totalCount = Await.result(size, Duration.Inf)
      page.setTotalPage()
    } catch {
      case _: Throwable => p.failure _
    }
    p.success(page)
    p.future
  }

}
